package ejb.cbm.seguridad.session;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import oracle.jdbc.OracleTypes;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import ejb.cbm.commons.FormatoFecha;
import ejb.cbm.commons.JdbcHelper;
import ejb.cbm.seguridad.bean.RegistroIngresoBean;
import ejb.cbm.seguridad.entity.RegistroIngresoEntity;
import ejb.cbm.seguridad.local.RegistroIngresoSessionLocal;

////@Stateless
@Service("registroIngresoSessionLocal")
public class RegistroIngresoSession extends HibernateDaoSupport implements RegistroIngresoSessionLocal {
	
	static Logger logger = Logger.getLogger(RegistroIngresoSession.class.getName());
	//property constants
	public static final String CODIGOTERMINAL = "codigoterminal";
	public static final String CODIGOOFICINA = "codigooficina";
	public static final String FLAGACTIVO = "flagactivo";
	public static final String USUARIOREGISTRO = "usuarioregistro";
	public static final String USUARIOMODIFICACION = "usuariomodificacion";


    //@PersistenceContext
    //private EntityManager entityManager;
	@Autowired
	public RegistroIngresoSession(SessionFactory sessionFactory){
		super.setSessionFactory(sessionFactory);
	}
    ////@TransactionAttribute(TransactionAttributeType.REQUIRED)
	@Transactional(propagation=Propagation.REQUIRED)
    public void save(RegistroIngresoEntity transientInstance) {
    	logger.log("saving RegistroIngresoEntity instance", Level.INFO, null,null);
        try {
            getSession().persist(transientInstance);
            logger.log("save successful", Level.INFO, null,null);
        } catch (RuntimeException re) {
        	logger.log("save failed", Level.FATAL,null, re);
            throw re;
        }
    }
    
    public void delete(RegistroIngresoEntity persistentInstance) {
    	logger.log("deleting RegistroIngresoEntity instance", Level.INFO, null,null);
        try {
            getSession().delete(persistentInstance);
            logger.log("delete successful", Level.INFO, null,null);
        } catch (RuntimeException re) {
        	logger.log("delete failed", Level.FATAL,null, re);
            throw re;
        }
    }
    @Transactional(propagation=Propagation.REQUIRED)
    public RegistroIngresoEntity update(RegistroIngresoEntity detachedInstance) {
    	logger.log("updating RegistroIngresoEntity instance", Level.INFO, null,null);
        try {
            RegistroIngresoEntity result = (RegistroIngresoEntity) getSession().merge(detachedInstance);
            logger.log("update successful", Level.INFO, null,null);
            return result;
        } catch (RuntimeException re) {
        	logger.log("update failed", Level.FATAL,null, re);
            throw re;
        }
    }
    
    public RegistroIngresoEntity findById( Long id) {
    	logger.log("finding RegistroIngresoEntity instance with id: " + id, Level.INFO, null,null);
        try {
            RegistroIngresoEntity instance = (RegistroIngresoEntity) getSession().get(RegistroIngresoEntity.class, id);
            return instance;
        } catch (RuntimeException re) {
        	logger.log("find failed", Level.FATAL,null, re);
            throw re;
        }
    }
    
    //@SuppressWarnings("unchecked")
    public List<RegistroIngresoEntity> findByProperty(String propertyName, Object value) {
    	logger.log("finding RegistroIngresoEntity instance with property: " + propertyName
    						+ ", value: " + value, Level.INFO, null,null);
		try {
			String queryString = "select model from RegistroIngresoEntity model where model." 
			 						+ propertyName + "= :propertyValue";
			return getSession().createQuery(queryString)
 				.setParameter("propertyValue", value).list();
		} catch (RuntimeException re) {
			logger.log("find by property name failed", Level.FATAL,null, re);
			throw re;
		}
	}
	
	public List<RegistroIngresoEntity> findByCodigoterminal(Object codigoterminal) {
		return findByProperty(CODIGOTERMINAL, codigoterminal);
	}
	
	public List<RegistroIngresoEntity> findByCodigooficina(Object codigooficina) {
		return findByProperty(CODIGOOFICINA, codigooficina);
	}
	
	public List<RegistroIngresoEntity> findByFlagactivo(Object flagactivo) {
		return findByProperty(FLAGACTIVO, flagactivo);
	}
	
	public List<RegistroIngresoEntity> findByUsuarioregistro(Object usuarioregistro) {
		return findByProperty(USUARIOREGISTRO, usuarioregistro);
	}
	
	public List<RegistroIngresoEntity> findByUsuariomodificacion(Object usuariomodificacion) {
		return findByProperty(USUARIOMODIFICACION, usuariomodificacion);
	}
	

	//@SuppressWarnings("unchecked")
	public List<RegistroIngresoEntity> findAll() {
		logger.log("finding all RegistroIngresoEntity instances", Level.INFO, null,null);
		try {
			String queryString = "select model from RegistroIngresoEntity model";
			return getSession().createQuery(queryString).list();
		} catch (RuntimeException re) {
			logger.log("find all failed", Level.FATAL,null, re);
			throw re;
		}
	}
	//@SuppressWarnings("unchecked")
	public List<RegistroIngresoEntity> findByFiltro(RegistroIngresoBean filtro){
		logger.log("findByFiltro RegistroIngresoEntity instance", Level.INFO, null, null);
		StringBuilder query = new StringBuilder();
		
		try{
			query.append("select ri ");
			
			query.append("from  RegistroIngresoEntity ri ");
			query.append("where 1 = 1 ");
			//query.append("from  RegistroIngresoEntity ri, UsuarioEntity us ");
			//query.append("where ri.codigousuario = us.codigousuario ");
			
			if (filtro.getFlagactivo()!=null){
				query.append("and ri.flagactivo = "+filtro.getFlagactivo());
			}
			if (filtro.getFlagestado()!=null){
				query.append(" and ri.flagestado = "+filtro.getFlagestado());
			}
			if (filtro.getCodigooficina()!=null){
				query.append(" and ri.codigooficina = "+JdbcHelper.to_char(filtro.getCodigooficina()));
			}
			//gclv 15/09/2011
			if (filtro.getCodigoterminal()!=null){
				query.append(" and ri.codigoterminal = '"+filtro.getCodigoterminal()+"'");
			}
			if (filtro.getCodigousuario()!=null){
				query.append(" and ri.codigousuario = "+JdbcHelper.to_char(filtro.getCodigousuario()));
			}
			if (filtro.getUsuarioBean().getApellidopaterno()!=null){
				query.append(" and upper(us.apellidopaterno) like '%"+filtro.getUsuarioBean().getApellidopaterno().toUpperCase()+"%' ");
			}
			if (filtro.getUsuarioBean().getApellidomaterno()!=null){
				query.append(" and upper(us.apellidomaterno) like '%"+filtro.getUsuarioBean().getApellidomaterno().toUpperCase()+"%' ");
			}
			if (filtro.getUsuarioBean().getNombre()!=null){
				query.append(" and upper(us.nombre) like '%"+filtro.getUsuarioBean().getNombre().toUpperCase()+"%' ");
			}
			if (filtro.getFecharegistro() != null){
				//query.append(" and to_char(ri.fecharegistro,'yyyymmdd') = "+JdbcHelper.to_char_yyyymmdd(filtro.getFecharegistro()));
				query.append(" and ri.fecharegistro >= :fechaIni and ri.fecharegistro < :fechaFin ");
			}
			
			Query q = getSession().createQuery(query.toString());
			
			if (filtro.getFecharegistro() != null){
				java.util.Date fechaIni = FormatoFecha.convertirFecha(FormatoFecha.formatearFecha(filtro.getFecharegistro(),"yyyyMMdd"), "yyyyMMdd");
				logger.info("fechaIni: "+fechaIni);
				java.util.Date fechaFin = FormatoFecha.agregarDias(fechaIni, 1);
				logger.info("fechaFin: "+fechaFin);
				q.setParameter("fechaIni", fechaIni);
				q.setParameter("fechaFin", fechaFin);
			}
			
			return q.list();
			
		}catch(RuntimeException e){
			logger.log("findByFiltro failed", Level.FATAL, null, e);
			throw e;
		}
	}
	
	/*********************************************************************
	 * Obtiene el registro de ingreso correspondiente a un dia determinado.
	 * Por cada dia solo deberia haber un resgistro de ingreso por usuario
	 ********************************************************************/
	//@SuppressWarnings("unchecked")
	public List<RegistroIngresoEntity> findLast(String codigoUsuario, String fecha){
		logger.log("findByFiltro RegistroIngresoEntity instance", Level.INFO, null, null);
		StringBuilder query = new StringBuilder();
		
		List<RegistroIngresoEntity> listado = null;
		
		try {
			java.util.Date fechaRegistro = new SimpleDateFormat("yyyyMMdd").parse(fecha);
			
			query.append("select model ");
			query.append("from  RegistroIngresoEntity model ");
			query.append("where model.codigousuario = :codigoUsuario");
			//query.append(" and to_char(model.fecharegistro,'yyyymmdd') = to_date(:fecha,'yyyymmdd')");
			query.append(" and model.fecharegistro >= :fecha");
				
			listado = getSession().createQuery(query.toString()).
					setParameter("codigoUsuario", codigoUsuario).
					setParameter("fecha", fechaRegistro).list();

		} catch(RuntimeException e){
			logger.log("findLast failed", Level.FATAL, null, e);
			throw e;
		} catch(Exception e){
			logger.log("findLast failed", Level.FATAL, null, e);
		}
		return listado;
	}
	
	//@SuppressWarnings("unchecked")
	public List<RegistroIngresoBean> findRegistrosByPerfil( Connection con, 
															RegistroIngresoBean filtro,
															String codigoUsuario,
															String codigoOficina,
															String tipoPerfil
													) throws SQLException{
		logger.log("findByFiltro RegistroIngresoEntity instance", Level.INFO, null, null);
		List<RegistroIngresoBean> lstResultado = new ArrayList<RegistroIngresoBean> ();
		
		try{
			
			CallableStatement cs = null;
			RegistroIngresoBean bean = null;
			ResultSet rs = null;
			
			try{
				cs = con.prepareCall("call CONNEG.PQ_CONTINUIDAD.sp_obtener_ingreso_perfil(?,?,?,?,?,?,?,?,?,?,?,?,?)");
				cs.setString(1,codigoUsuario);
				cs.setString(2,tipoPerfil);
				cs.setString(3,codigoOficina);
				cs.setString(4,(filtro.getFlagactivo()==null?null:filtro.getFlagactivo().toString()));
				cs.setString(5,(filtro.getFlagestado()==null?null:filtro.getFlagestado().toString()));
				cs.setString(6,filtro.getCodigooficina());
				cs.setString(7,filtro.getCodigoterminal());
				cs.setString(8,filtro.getUsuarioBean().getCodigousuario());
				cs.setString(9,filtro.getUsuarioBean().getApellidopaterno());
				cs.setString(10,filtro.getUsuarioBean().getApellidomaterno());
				cs.setString(11,filtro.getUsuarioBean().getNombre());
				cs.setString(12,filtro.getFecha());
				cs.registerOutParameter(13,OracleTypes.CURSOR);
				
				cs.executeQuery();
				rs = (ResultSet)cs.getObject(13);
				
				while(rs.next()){
					bean = new RegistroIngresoBean();
					bean.setNumeroregistro(rs.getLong("NUMEROREGISTRO"));
					bean.setCodigousuario(rs.getString("CODIGOUSUARIO"));
					bean.setCodigoterminal(rs.getString("CODIGOTERMINAL"));
					bean.setCodigoPuesto(rs.getString("CODIGOPUESTO"));
					bean.setCodigooficina(rs.getString("CODIGOOFICINA"));
					bean.setNombre(rs.getString("NOMBRE"));
					bean.setApellidopaterno(rs.getString("APELLIDOPATERNO"));
					bean.setApellidomaterno(rs.getString("APELLIDOMATERNO"));
					bean.setFlagestado(rs.getLong("FLAGESTADO"));
					bean.setFlagactivo(rs.getLong("FLAGACTIVO"));
					bean.setUsuarioregistro(rs.getString("USUARIOREGISTRO"));
					bean.setFecharegistro(new Date(rs.getDate("FECHAREGISTRO").getTime()));
					bean.setUsuariomodificacion(rs.getString("USUARIOMODIFICACION"));
					bean.setFechamodificacion(new Date(rs.getDate("FECHAMODIFICACION").getTime()));
					lstResultado.add(bean);
				}
			}catch (Exception e) {
				e.printStackTrace();logger.error(e);
			}
			finally{
				JdbcHelper.close(null,cs,null,null,rs);
			}
			
			return lstResultado;
			
		}catch(RuntimeException e){
			logger.log("findByFiltro failed", Level.FATAL, null, e);
			throw e;
		}
	}
	
}